package com.mvc.core.utils.task;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 
 * 延时队列任务管理
 * 
 * @author 李涛
 * @version 创建时间：2018年6月16日 下午3:35:39
 */
public class TaskQueueBean {

	private TaskQueueBean() {
	}

	private static class LazyHolder {
		private static TaskQueueBean taskQueueDaemonThread = new TaskQueueBean();

	}

	public static TaskQueueBean getInstance() {
		return LazyHolder.taskQueueDaemonThread;
	}

	Executor executor = Executors.newFixedThreadPool(20);
	/**
	 * 守护线程
	 */
	private Thread daemonThread;

	/**
	 * 初始化守护线程
	 */
	public void init() {
		daemonThread = new Thread() {
			public void run() {
				execute();
			}
		};
		daemonThread.setDaemon(true);
		daemonThread.setName("Task Queue Daemon Thread");
		daemonThread.start();
		System.out.println("~~~~~~~~~~~~~~~~~~~~延时任务开启~~~~~~~~~~~~~~~~~~~~~~~~~");
	}

	private void execute() {
		System.out.println("start:" + System.currentTimeMillis());
		while (true) {
			try {
				// 从延迟队列中取值,如果没有对象过期则队列一直等待，
				DelayedTask t1 = t.take();
				if (t1 != null) {
					// 修改问题的状态
					Runnable task = t1.getTask();
					if (task == null) {
						continue;
					}
					executor.execute(task);
					System.out.println("[at task:" + task + "]   [Time:" + System.currentTimeMillis() + "]");
				}
			} catch (Exception e) {
				e.printStackTrace();
				break;
			}
		}
	}

	/**
	 * 创建一个最初为空的新 DelayQueue
	 */
	private static DelayQueue<DelayedTask> t = new DelayQueue<>();

	/**
	 * 添加任务， time 延迟时间 task 任务 用户为问题设置延迟时间
	 */
	public void put(long time, Runnable task, String taskName) {
		// 转换成ns
		long nanoTime = TimeUnit.NANOSECONDS.convert(time, TimeUnit.MILLISECONDS);
		// 创建一个任务
		DelayedTask k = new DelayedTask(nanoTime, task);
		// 将任务放在延迟的队列中
		t.put(k);
		System.out.println("~~~~~~~~~~~~~~~~~~~~新任务:\"" + taskName + "\"加入队列~~~~~~~~~~~~~~~~~~~~~~~~~");
	}

	/**
	 * 结束
	 * 
	 * @param task
	 */
	public boolean endTask(DelayedTask<Runnable> task) {
		return t.remove(task);
	}
}
